#pragma once

#include "cmath"

namespace GraphGradient {

    double l2distance(const float *a, const float *b, int vec_dim) {
        double dis = 0;
        for (int i = 0; i < vec_dim; ++i) {
            double tmp = a[i] - b[i];
            dis += (tmp * tmp);
        }
        return dis;
    }

    //count the cosine of angle a b c, the vector ba * bc
    double cosineDistance(const float *a, const float *b, const float *c, int vec_dim) {
        double time_res = 0;
        double mod_vec1 = 0;
        double mod_vec2 = 0;

        for (int i = 0; i < vec_dim; i++) {
            float vec_num1 = a[i] - b[i];
            float vec_num2 = c[i] - b[i];
            time_res += vec_num1 * vec_num2;
            mod_vec1 += vec_num1 * vec_num1;
            mod_vec2 += vec_num2 * vec_num2;
        }
        return time_res / (sqrt(mod_vec1) * sqrt(mod_vec2));
    }

    class edge_stop_condition {
    public:
        double query_dist_;
        int idx_;
        double last_this_dist_;
        double last_query_dist_;

        edge_stop_condition(double query_dist, int idx,
                            double last_this_dist, double last_query_dist) :
                query_dist_(query_dist), idx_(idx),
                last_this_dist_(last_this_dist), last_query_dist_(last_query_dist) {}

        edge_stop_condition() {
            query_dist_ = 0;
            idx_ = -1;
            last_this_dist_ = 0;
            last_query_dist_ = 0;
        }
    };

    struct edge_stop_condition_min_heap {
        constexpr bool operator()(edge_stop_condition const &a, edge_stop_condition const &b) const noexcept {
            return a.query_dist_ > b.query_dist_; //<大顶堆, >小顶堆
        }
    };

    class distance_cmp {
    public:
        double distance_;
        int idx_;

        distance_cmp(double distance, int idx) : distance_(distance), idx_(idx) {}

        distance_cmp() {
            distance_ = 0;
            idx_ = -1;
        }
    };

    struct distance_min_heap {
        constexpr bool operator()(distance_cmp const &a, distance_cmp const &b) const noexcept {
            return a.distance_ > b.distance_; //<大顶堆, >小顶堆
        }
    };

    struct distance_max_heap {
        constexpr bool operator()(distance_cmp const &a, distance_cmp const &b) const noexcept {
            return a.distance_ < b.distance_; //<大顶堆, >小顶堆
        }
    };

}